/**
 * @file mv88e1512_driver.h
 * @brief 88E1512 Gigabit Ethernet PHY transceiver
 *
 * @section License
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneTCP Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 1.9.4
 **/

#ifndef _MV88E1512_DRIVER_H
#define _MV88E1512_DRIVER_H

//Dependencies
#include "core/nic.h"

//PHY address
#ifndef MV88E1512_PHY_ADDR
   #define MV88E1512_PHY_ADDR 0
#elif (MV88E1512_PHY_ADDR < 0 || MV88E1512_PHY_ADDR > 31)
   #error MV88E1512_PHY_ADDR parameter is not valid
#endif

//88E1512 PHY registers
#define MV88E1512_BMCR                         0x00
#define MV88E1512_BMSR                         0x01
#define MV88E1512_PHYID1                       0x02
#define MV88E1512_PHYID2                       0x03
#define MV88E1512_ANAR                         0x04
#define MV88E1512_ANLPAR                       0x05
#define MV88E1512_ANER                         0x06
#define MV88E1512_ANNPR                        0x07
#define MV88E1512_ANLPNPR                      0x08
#define MV88E1512_GBCR                         0x09
#define MV88E1512_GBSR                         0x0A
#define MV88E1512_GBESR                        0x0F
#define MV88E1512_SCR1                         0x10
#define MV88E1512_SSR1                         0x11
#define MV88E1512_IER                          0x12
#define MV88E1512_ISR                          0x13
#define MV88E1512_SCR2                         0x14
#define MV88E1512_RECR                         0x15
#define MV88E1512_PAGSR                        0x16
#define MV88E1512_GISR                         0x17

//Copper Control register
#define MV88E1512_BMCR_RESET                   0x8000
#define MV88E1512_BMCR_LOOPBACK                0x4000
#define MV88E1512_BMCR_SPEED_SEL_LSB           0x2000
#define MV88E1512_BMCR_AN_EN                   0x1000
#define MV88E1512_BMCR_POWER_DOWN              0x0800
#define MV88E1512_BMCR_ISOLATE                 0x0400
#define MV88E1512_BMCR_RESTART_AN              0x0200
#define MV88E1512_BMCR_DUPLEX_MODE             0x0100
#define MV88E1512_BMCR_COL_TEST                0x0080
#define MV88E1512_BMCR_SPEED_SEL_MSB           0x0040

//Copper Status register
#define MV88E1512_BMSR_100BT4                  0x8000
#define MV88E1512_BMSR_100BTX_FD               0x4000
#define MV88E1512_BMSR_100BTX_HD               0x2000
#define MV88E1512_BMSR_10BT_FD                 0x1000
#define MV88E1512_BMSR_10BT_HD                 0x0800
#define MV88E1512_BMSR_100BT2_FD               0x0400
#define MV88E1512_BMSR_100BT2_HD               0x0200
#define MV88E1512_BMSR_EXTENDED_STATUS         0x0100
#define MV88E1512_BMSR_MF_PREAMBLE_SUPPR       0x0040
#define MV88E1512_BMSR_AN_COMPLETE             0x0020
#define MV88E1512_BMSR_REMOTE_FAULT            0x0010
#define MV88E1512_BMSR_AN_CAPABLE              0x0008
#define MV88E1512_BMSR_LINK_STATUS             0x0004
#define MV88E1512_BMSR_JABBER_DETECT           0x0002
#define MV88E1512_BMSR_EXTENDED_CAPABLE        0x0001

//PHY Identifier 1 register
#define MV88E1512_PHYID1_OUI_MSB               0xFFFF
#define MV88E1512_PHYID1_OUI_MSB_DEFAULT       0x0141

//PHY Identifier 2 register
#define MV88E1512_PHYID2_OUI_LSB               0xFC00
#define MV88E1512_PHYID2_OUI_LSB_DEFAULT       0x0C00
#define MV88E1512_PHYID2_MODEL_NUM             0x03F0
#define MV88E1512_PHYID2_MODEL_NUM_DEFAULT     0x01D0
#define MV88E1512_PHYID2_REVISION_NUM          0x000F

//Copper Auto-Negotiation Advertisement register
#define MV88E1512_ANAR_NEXT_PAGE               0x8000
#define MV88E1512_ANAR_ACK                     0x4000
#define MV88E1512_ANAR_REMOTE_FAULT            0x2000
#define MV88E1512_ANAR_ASYM_PAUSE              0x0800
#define MV88E1512_ANAR_PAUSE                   0x0400
#define MV88E1512_ANAR_100BT4                  0x0200
#define MV88E1512_ANAR_100BTX_FD               0x0100
#define MV88E1512_ANAR_100BTX_HD               0x0080
#define MV88E1512_ANAR_10BT_FD                 0x0040
#define MV88E1512_ANAR_10BT_HD                 0x0020
#define MV88E1512_ANAR_SELECTOR                0x001F
#define MV88E1512_ANAR_SELECTOR_DEFAULT        0x0001

//Copper Link Partner Ability register
#define MV88E1512_ANLPAR_NEXT_PAGE             0x8000
#define MV88E1512_ANLPAR_ACK                   0x4000
#define MV88E1512_ANLPAR_REMOTE_FAULT          0x2000
#define MV88E1512_ANLPAR_TECH_ABLE             0x1000
#define MV88E1512_ANLPAR_ASYM_PAUSE            0x0800
#define MV88E1512_ANLPAR_PAUSE                 0x0400
#define MV88E1512_ANLPAR_100BT4                0x0200
#define MV88E1512_ANLPAR_100BTX_FD             0x0100
#define MV88E1512_ANLPAR_100BTX_HD             0x0080
#define MV88E1512_ANLPAR_10BT_FD               0x0040
#define MV88E1512_ANLPAR_10BT_HD               0x0020
#define MV88E1512_ANLPAR_SELECTOR              0x001F
#define MV88E1512_ANLPAR_SELECTOR_DEFAULT      0x0001

//Copper Auto-Negotiation Expansion register
#define MV88E1512_ANER_PAR_DETECT_FAULT        0x0010
#define MV88E1512_ANER_LP_NEXT_PAGE_ABLE       0x0008
#define MV88E1512_ANER_NEXT_PAGE_ABLE          0x0004
#define MV88E1512_ANER_PAGE_RECEIVED           0x0002
#define MV88E1512_ANER_LP_AN_ABLE              0x0001

//Copper Next Page Transmit register
#define MV88E1512_ANNPR_NEXT_PAGE              0x8000
#define MV88E1512_ANNPR_MSG_PAGE               0x2000
#define MV88E1512_ANNPR_ACK2                   0x1000
#define MV88E1512_ANNPR_TOGGLE                 0x0800
#define MV88E1512_ANNPR_MESSAGE                0x07FF

//Copper Link Partner Next Page register
#define MV88E1512_ANLPNPR_NEXT_PAGE            0x8000
#define MV88E1512_ANLPNPR_ACK                  0x4000
#define MV88E1512_ANLPNPR_MSG_PAGE             0x2000
#define MV88E1512_ANLPNPR_ACK2                 0x1000
#define MV88E1512_ANLPNPR_TOGGLE               0x0800
#define MV88E1512_ANLPNPR_MESSAGE              0x07FF

//1000BASE-T Control register
#define MV88E1512_GBCR_TEST_MODE               0xE000
#define MV88E1512_GBCR_MS_MAN_CONF_EN          0x1000
#define MV88E1512_GBCR_MS_MAN_CONF_VAL         0x0800
#define MV88E1512_GBCR_PORT_TYPE               0x0400
#define MV88E1512_GBCR_1000BT_FD               0x0200
#define MV88E1512_GBCR_1000BT_HD               0x0100

//1000BASE-T Status register
#define MV88E1512_GBSR_MS_CONF_FAULT           0x8000
#define MV88E1512_GBSR_MS_CONF_RES             0x4000
#define MV88E1512_GBSR_LOCAL_RECEIVER_STATUS   0x2000
#define MV88E1512_GBSR_REMOTE_RECEIVER_STATUS  0x1000
#define MV88E1512_GBSR_LP_1000BT_FD            0x0800
#define MV88E1512_GBSR_LP_1000BT_HD            0x0400
#define MV88E1512_GBSR_IDLE_ERR_COUNT          0x00FF

//Extended Status register
#define MV88E1512_GBESR_1000BX_FD              0x8000
#define MV88E1512_GBESR_1000BX_HD              0x4000
#define MV88E1512_GBESR_1000BT_FD              0x2000
#define MV88E1512_GBESR_1000BT_HD              0x1000

//Copper Specific Control 1 register
#define MV88E1512_SCR1_LINK_PULSE_DIS          0x8000
#define MV88E1512_SCR1_FORCE_LINK_GOOD         0x0400
#define MV88E1512_SCR1_ENERGY_DETECT           0x0300
#define MV88E1512_SCR1_MDIX_MODE               0x0060
#define MV88E1512_SCR1_MDIX_MODE_MANUAL_MDI    0x0000
#define MV88E1512_SCR1_MDIX_MODE_MANUAL_MDIX   0x0020
#define MV88E1512_SCR1_MDIX_MODE_AUTO          0x0060
#define MV88E1512_SCR1_TX_DIS                  0x0008
#define MV88E1512_SCR1_POWER_DOWN              0x0004
#define MV88E1512_SCR1_POLARITY_REVERSAL_DIS   0x0002
#define MV88E1512_SCR1_JABBER_DIS              0x0001

//Copper Specific Status 1 register
#define MV88E1512_SSR1_SPEED                   0xC000
#define MV88E1512_SSR1_SPEED_10MBPS            0x0000
#define MV88E1512_SSR1_SPEED_100MBPS           0x4000
#define MV88E1512_SSR1_SPEED_1000MBPS          0x8000
#define MV88E1512_SSR1_DUPLEX                  0x2000
#define MV88E1512_SSR1_PAGE_RECEIVED           0x1000
#define MV88E1512_SSR1_SPEED_DUPLEX_RESOLVED   0x0800
#define MV88E1512_SSR1_LINK                    0x0400
#define MV88E1512_SSR1_TX_PAUSE_EN             0x0200
#define MV88E1512_SSR1_RX_PAUSE_EN             0x0100
#define MV88E1512_SSR1_MDI_CROSSOVER_STATUS    0x0040
#define MV88E1512_SSR1_ENERGY_DETECT_STATUS    0x0010
#define MV88E1512_SSR1_GLOBAL_LINK_STATUS      0x0008
#define MV88E1512_SSR1_POLARITY                0x0002
#define MV88E1512_SSR1_JABBER                  0x0001

//Copper Specific Interrupt Enable register
#define MV88E1512_IER_AN_ERROR                 0x8000
#define MV88E1512_IER_SPEED_CHANGED            0x4000
#define MV88E1512_IER_DUPLEX_CHANGED           0x2000
#define MV88E1512_IER_PAGE_RECEIVED            0x1000
#define MV88E1512_IER_AN_COMPLETE              0x0800
#define MV88E1512_IER_LINK_STATUS_CHANGED      0x0400
#define MV88E1512_IER_SYMBOL_ERROR             0x0200
#define MV88E1512_IER_FALSE_CARRIER            0x0100
#define MV88E1512_IER_MDI_CROSSOVER_CHANGED    0x0040
#define MV88E1512_IER_ENERGY_DETECT            0x0010
#define MV88E1512_IER_FLP_COMPLETE             0x0008
#define MV88E1512_IER_POLARITY_CHANGED         0x0002
#define MV88E1512_IER_JABBER                   0x0001

//Copper Interrupt Status register
#define MV88E1512_ISR_AN_ERROR                 0x8000
#define MV88E1512_ISR_SPEED_CHANGED            0x4000
#define MV88E1512_ISR_DUPLEX_CHANGED           0x2000
#define MV88E1512_ISR_PAGE_RECEIVED            0x1000
#define MV88E1512_ISR_AN_COMPLETE              0x0800
#define MV88E1512_ISR_LINK_STATUS_CHANGED      0x0400
#define MV88E1512_ISR_SYMBOL_ERROR             0x0200
#define MV88E1512_ISR_FALSE_CARRIER            0x0100
#define MV88E1512_ISR_MDI_CROSSOVER_CHANGED    0x0040
#define MV88E1512_ISR_ENERGY_DETECT            0x0010
#define MV88E1512_ISR_FLP_COMPLETE             0x0008
#define MV88E1512_ISR_POLARITY_CHANGED         0x0002
#define MV88E1512_ISR_JABBER                   0x0001

//Copper Specific Control 2 register
#define MV88E1512_SCR2_BREAK_LINK_ON_INSUF_IPG 0x0040
#define MV88E1512_SCR2_REVERSE_MDIPN3_TX_POL   0x0008
#define MV88E1512_SCR2_REVERSE_MDIPN2_TX_POL   0x0004
#define MV88E1512_SCR2_REVERSE_MDIPN1_TX_POL   0x0002
#define MV88E1512_SCR2_REVERSE_MDIPN0_TX_POL   0x0001

//Page Address register
#define MV88E1512_PAGSR_PAGE_SEL               0x00FF

//Global Interrupt Status register
#define MV88E1512_GISR_INTERRUPT               0x0001

//C++ guard
#ifdef __cplusplus
   extern "C" {
#endif

//88E1512 Ethernet PHY driver
extern const PhyDriver mv88e1512PhyDriver;

//88E1512 related functions
error_t mv88e1512Init(NetInterface *interface);

void mv88e1512Tick(NetInterface *interface);

void mv88e1512EnableIrq(NetInterface *interface);
void mv88e1512DisableIrq(NetInterface *interface);

void mv88e1512EventHandler(NetInterface *interface);

void mv88e1512WritePhyReg(NetInterface *interface, uint8_t address,
   uint16_t data);

uint16_t mv88e1512ReadPhyReg(NetInterface *interface, uint8_t address);

void mv88e1512DumpPhyReg(NetInterface *interface);

//C++ guard
#ifdef __cplusplus
   }
#endif

#endif
